#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#define MAX_CMD_LEN 81

/*
Every command is assigned a number. This file provides the matching between commandName, like 'start' and the code e.g 1

@KAI: The command names derive a little bit from you specification, because they were too long and unhandy to type. The following command names are a compromise between readability and brevity.
@KAI: The specification has a time command. I think we cannot implement that. PingPong says nothing that this is required.

*/

#define CMD_NOT_RECOGNIZED -1

#define CMD_EXIT_SHELL 0
char cmd_0[] = "exit";

#define CMD_START_PROC 1
char cmd_1[] = "start";

#define CMD_CHANGE_PRIORITY 2
char cmd_2[] = "priority";

#define CMD_GET_INFO 3
char cmd_3[] = "procinfo";

#define CMD_TERMINATE 4
char cmd_4[] = "kill";

#define CMD_ECHO 5
char cmd_5[] = "echo";

#define CMD_ECHO_MALTA 6
char cmd_6[] = "echomalta";

#define CMD_HELP 7
char cmd_7[] = "help";

//Won't do these until good justification

/*#define CMD_DELAY 8
char cmd_8[] = "delay";

#define CMD_BLOCK 9
char cmd_9[] = "procblock";*/


//[VW] This function was copied from libc, maybe it should be moved into the API, if it is useful for other programs.
int porn_strncmp (s1, s2, n)
     
     const char *s1;
     const char *s2;
     size_t n;

{
  
  //unsigned reg_char c1 = '\0';
  //unsigned reg_char c2 = '\0';
  char c1 = '\0';
  char c2 = '\0';

  if (n >= 4)
    {
      size_t n4 = n >> 2;
      do
	{
	  c1 = (unsigned char) *s1++;
	  c2 = (unsigned char) *s2++;
	  if (c1 == '\0' || c1 != c2)
	    return c1 - c2;
	  c1 = (unsigned char) *s1++;
	  c2 = (unsigned char) *s2++;
	  if (c1 == '\0' || c1 != c2)
	    return c1 - c2;
	  c1 = (unsigned char) *s1++;
	  c2 = (unsigned char) *s2++;
	  if (c1 == '\0' || c1 != c2)
	    return c1 - c2;
	  c1 = (unsigned char) *s1++;
	  c2 = (unsigned char) *s2++;
	  if (c1 == '\0' || c1 != c2)
	    return c1 - c2;
	} while (--n4 > 0);
      n &= 3;
    }

  while (n > 0)
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
	return c1 - c2;
      n--;
    }

  return c1 - c2;
}

//modified for command recognition
int porn_strncmp_space (s1, s2, n)
     
     const char *s1;
     const char *s2;
     size_t n;

{
  
  char c1 = '\0';
  char c2 = '\0';

  while (n > 0)
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
   
      /*mod, we recognize a command in the following case
       
	it is followed by a LF (hex a) (parameterless command)
	it is followed by a SP (hex 20) (parameters might follow)
       
       */
      if(c1 == '\xa' && c2 == '\0' || c1 == '\x20' && c2 == '\0'){
	return 0;
      }

      if (c1 == '\0' || c1 != c2)
	return c1 - c2;
      n--;
    }

  return c1 - c2;
}


int porn_strlen(char* str){

  int len = 0;

  while(str[len] != 0){
    len++;
  }

  return len;

}

/* Copy no more than N bytes of SRC to DEST, stopping when C is found.
   Return the position in DEST one byte past where C was copied, or
   NULL if C was not found in the first N bytes of SRC.  */
void * porn_memccpy (dest, src, n)
      void *dest;
      const void *src;
      size_t n;
{
  
  register const char *s = src;
  register char *d = dest;
  register size_t i = n;

  while (i-- > 0){
   
    //we copy until we find a sp or lf
    
    *d = *s; //copy character
    if (*s == '\x20' || *s == '\xa'){ //check if we are finished
      *d = '\x0'; //don't forget the 0 termination
      return d;
    }
    
    d++;s++;
    
  }
  return NULL;
}


//convert a string to a int
int porn_str2int(char* str){

  int res = 0; //here we store the result
  int len = porn_strlen(str);
  int digit_value; //value of the single digits
  int i,  power = 1;
  int error = 0;

  //We walk through the string backwards
  for(i = len; i--; i>=0){
  
    switch(str[i]){

    case '0':
      digit_value = 0;
      break;
    case '1':
      digit_value = 1;
      break;
    case '2':
      digit_value = 2;
      break;
    case '3':
      digit_value = 3;
      break;
    case '4':
      digit_value = 4;
      break;
    case '5':
      digit_value = 5;
      break;
    case '6':
      digit_value = 6;
      break;
    case '7':
      digit_value = 7;
      break;
    case '8':
      digit_value = 8;
      break;
    case '9':
      digit_value = 9;
      break;      
    default:
      error = 1;
    }

    res += digit_value * power;
    power *= 10;

  }

  if(!error)
    return res;
  else
    return -1;
  
}
